package api

import (
	"context"
	"encoding/json"
	"fmt"
	"net/http"
	"strings"
	"sync"
	"sync/atomic"
	"time"

	"github.com/catroll/fastdns/internal/config"
	"github.com/catroll/fastdns/internal/dns"
	"github.com/catroll/fastdns/internal/logger"
)

// Server 表示 API 服务器
type Server struct {
	config     *config.Config
	resolver   *dns.Resolver
	server     *http.Server
	startTime  time.Time
	queryCount *int64
}

// NewServer 创建一个新的 API 服务器
func NewServer(cfg *config.Config, resolver *dns.Resolver, queryCount *int64) *Server {
	return &Server{
		config:     cfg,
		resolver:   resolver,
		startTime:  time.Now(),
		queryCount: queryCount,
	}
}

// Start 启动 API 服务器
func (s *Server) Start() error {
	mux := http.NewServeMux()

	// 注册路由
	s.registerRoutes(mux)

	s.server = &http.Server{
		Addr:    s.config.Server.APIListen,
		Handler: mux,
	}

	logger.Info("API 服务器启动", "address", s.config.Server.APIListen)
	return s.server.ListenAndServe()
}

// Stop 停止 API 服务器
func (s *Server) Stop(ctx context.Context) error {
	logger.Info("API 服务器关闭中...")
	return s.server.Shutdown(ctx)
}

// registerRoutes 注册 API 路由
func (s *Server) registerRoutes(mux *http.ServeMux) {
	// 健康检查
	mux.HandleFunc("/api/v1/health", WrapHandlerWithLogging(s.handleHealth))

	// 服务状态
	mux.HandleFunc("/api/v1/status", WrapHandlerWithLogging(s.handleStatus))

	// DNS 上游服务器管理
	mux.HandleFunc("/api/v1/dns/upstream", WrapHandlerWithLogging(s.handleUpstream))

	// DNS 缓存管理
	mux.HandleFunc("/api/v1/dns/cache", WrapHandlerWithLogging(s.handleCache))

	// DNS 查询
	mux.HandleFunc("/api/v1/dns/query", WrapHandlerWithLogging(s.handleQuery))

	// 邮件域名查询
	mux.HandleFunc("/api/v1/dns/maildomain", WrapHandlerWithLogging(s.handleMailDomain))

	logger.Info("已为所有 API 路由添加详细日志记录和 OPTIONS 方法支持")
}

// handleHealth 处理健康检查请求
func (s *Server) handleHealth(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodGet {
		http.Error(w, "方法不允许", http.StatusMethodNotAllowed)
		return
	}

	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusOK)
	json.NewEncoder(w).Encode(map[string]string{
		"status": "healthy",
	})
}

// handleStatus 处理服务状态请求
func (s *Server) handleStatus(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodGet {
		http.Error(w, "方法不允许："+r.Method, http.StatusMethodNotAllowed)
		return
	}

	// 获取缓存统计信息
	cacheSize, cacheCapacity := s.resolver.GetCacheStats()
	var cacheHitRatio float64
	if s.config.DNS.Cache.Enabled {
		// 这里假设 resolver 提供了获取缓存命中率的方法
		// 实际实现中需要添加相应的方法
		cacheHitRatio = 0.0 // 示例值
	}

	uptime := time.Since(s.startTime).String()

	queries := int64(0)
	if s.queryCount != nil {
		queries = atomic.LoadInt64(s.queryCount)
	}

	response := map[string]any{
		"status":            "running",
		"uptime":            uptime,
		"queries_processed": queries,
		"cache_enabled":     s.config.DNS.Cache.Enabled,
		"cache_size":        cacheSize,
		"cache_capacity":    cacheCapacity,
	}

	if s.config.DNS.Cache.Enabled {
		response["cache_hit_ratio"] = cacheHitRatio
	}

	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusOK)
	json.NewEncoder(w).Encode(response)
}

// UpstreamRequest 表示添加上游 DNS 服务器的请求
type UpstreamRequest struct {
	Address  string        `json:"address"`
	Protocol string        `json:"protocol"`
	Timeout  time.Duration `json:"timeout"`
	Priority int           `json:"priority"`
}

// handleUpstream 处理上游 DNS 服务器管理请求
func (s *Server) handleUpstream(w http.ResponseWriter, r *http.Request) {
	switch r.Method {
	case http.MethodGet:
		// 获取所有上游 DNS 服务器
		upstreams := s.resolver.GetUpstreamServers()

		// 转换为响应格式
		response := make([]map[string]any, 0, len(upstreams))
		for _, us := range upstreams {
			status := "healthy"
			if !us.Healthy() {
				status = "unhealthy"
			}

			response = append(response, map[string]any{
				"address":  us.Address,
				"protocol": us.Protocol,
				"timeout":  us.Timeout.String(),
				"priority": us.Priority,
				"status":   status,
				"latency":  us.Latency().String(),
			})
		}

		w.Header().Set("Content-Type", "application/json")
		w.WriteHeader(http.StatusOK)
		json.NewEncoder(w).Encode(map[string]any{
			"upstream_servers": response,
		})

	case http.MethodPost:
		// 添加新的上游 DNS 服务器
		var req UpstreamRequest
		if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
			http.Error(w, "无效的请求体", http.StatusBadRequest)
			return
		}

		// 验证请求
		if req.Address == "" {
			http.Error(w, "地址不能为空", http.StatusBadRequest)
			return
		}
		if req.Protocol != "udp" && req.Protocol != "tcp" {
			http.Error(w, "协议必须是 'udp' 或 'tcp'", http.StatusBadRequest)
			return
		}
		if req.Timeout <= 0 {
			req.Timeout = 5 * time.Second // 默认超时
		}

		// 添加上游服务器
		err := s.resolver.AddUpstreamServer(req.Address, req.Protocol, req.Timeout, req.Priority)
		if err != nil {
			http.Error(w, err.Error(), http.StatusBadRequest)
			return
		}

		w.Header().Set("Content-Type", "application/json")
		w.WriteHeader(http.StatusCreated)
		json.NewEncoder(w).Encode(map[string]string{
			"status":  "success",
			"message": fmt.Sprintf("上游 DNS 服务器 %s 已添加", req.Address),
		})

	case http.MethodDelete:
		// 删除上游 DNS 服务器
		address := r.URL.Query().Get("address")
		if address == "" {
			http.Error(w, "缺少 address 参数", http.StatusBadRequest)
			return
		}

		err := s.resolver.RemoveUpstreamServer(address)
		if err != nil {
			http.Error(w, err.Error(), http.StatusBadRequest)
			return
		}

		w.Header().Set("Content-Type", "application/json")
		w.WriteHeader(http.StatusOK)
		json.NewEncoder(w).Encode(map[string]string{
			"status":  "success",
			"message": fmt.Sprintf("上游 DNS 服务器 %s 已移除", address),
		})

	default:
		http.Error(w, "方法不允许", http.StatusMethodNotAllowed)
	}
}

// handleCache 处理 DNS 缓存管理请求
func (s *Server) handleCache(w http.ResponseWriter, r *http.Request) {
	if !s.config.DNS.Cache.Enabled {
		http.Error(w, "缓存未启用", http.StatusBadRequest)
		return
	}

	switch r.Method {
	case http.MethodGet:
		// 获取缓存统计信息
		cacheSize, cacheCapacity := s.resolver.GetCacheStats()

		w.Header().Set("Content-Type", "application/json")
		w.WriteHeader(http.StatusOK)
		json.NewEncoder(w).Encode(map[string]any{
			"size":     cacheSize,
			"capacity": cacheCapacity,
			"ttl":      s.config.DNS.Cache.TTL.String(),
		})

	case http.MethodDelete:
		// 清除缓存
		s.resolver.ClearCache()

		w.Header().Set("Content-Type", "application/json")
		w.WriteHeader(http.StatusOK)
		json.NewEncoder(w).Encode(map[string]string{
			"status":  "success",
			"message": "DNS 缓存已清除",
		})

	default:
		http.Error(w, "方法不允许", http.StatusMethodNotAllowed)
	}
}

// QueryRequest 表示 DNS 查询请求
type QueryRequest struct {
	Domain    string `json:"domain"`
	Type      string `json:"type,omitempty"`       // 记录类型：A, AAAA, CNAME, MX, TXT, NS 等
	SmartMode bool   `json:"smart_mode,omitempty"` // 是否启用智能查询模式
}

// MailDomainRequest 邮件域名查询请求
type MailDomainRequest struct {
	Domain    string   `json:"domain"`
	Selectors []string `json:"selectors,omitempty"`  // 可选的 DKIM selectors 列表
	SmartMode bool     `json:"smart_mode,omitempty"` // 是否启用智能查询模式
}

// handleQuery 处理 DNS 查询请求
func (s *Server) handleQuery(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		http.Error(w, "方法不允许", http.StatusMethodNotAllowed)
		return
	}

	var req QueryRequest
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		http.Error(w, "无效的请求体", http.StatusBadRequest)
		return
	}

	if req.Domain == "" {
		http.Error(w, "域名不能为空", http.StatusBadRequest)
		return
	}

	// 执行 DNS 查询
	ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second)
	defer cancel()

	// 默认查询类型为 A 记录
	recordType := req.Type
	if recordType == "" {
		recordType = "A"
	}

	// 增加查询计数
	if s.queryCount != nil {
		atomic.AddInt64(s.queryCount, 1)
	}

	// 根据记录类型执行不同的查询
	switch recordType {
	case "A", "AAAA":
		// 查询 IP 地址
		ips, err := s.resolver.LookupIP(ctx, req.Domain)
		if err != nil {
			http.Error(w, fmt.Sprintf("DNS 查询失败: %v", err), http.StatusInternalServerError)
			return
		}

		// 转换 IP 地址为字符串
		ipStrings := make([]string, 0, len(ips))
		for _, ip := range ips {
			ipStrings = append(ipStrings, ip.String())
		}

		w.Header().Set("Content-Type", "application/json")
		w.WriteHeader(http.StatusOK)
		json.NewEncoder(w).Encode(map[string]any{
			"domain":  req.Domain,
			"type":    recordType,
			"records": ipStrings,
			"ttl":     s.config.DNS.Cache.TTL.Seconds(),
		})
		return

	default:
		// 查询指定类型的记录
		records, err := s.resolver.LookupRecords(ctx, req.Domain, dns.RecordType(recordType))
		if err != nil {
			// 如果启用了智能查询模式且是 A/AAAA 记录查询失败，尝试查询 CNAME 记录
			if req.SmartMode && (recordType == "A" || recordType == "AAAA") {
				logger.Debug("智能模式: IP 查询失败，尝试 CNAME", "domain", req.Domain)

				// 查询 CNAME 记录
				cnameRecords, cnameErr := s.resolver.LookupRecords(ctx, req.Domain, dns.RTypeCNAME)
				if cnameErr == nil && len(cnameRecords) > 0 {
					// 找到 CNAME 记录
					records = cnameRecords

					// 从 CNAME 记录中提取目标域名
					var targetDomain string
					if cnameRecord, ok := cnameRecords[0].(dns.DNSRecord); ok {
						targetDomain = cnameRecord.Value
						logger.Debug("智能模式: 找到 CNAME", "domain", req.Domain, "cname", targetDomain)

						// 查询 CNAME 指向域名的 IP 地址
						ipRecords, ipErr := s.resolver.LookupRecords(ctx, targetDomain, dns.RecordType(recordType))
						if ipErr == nil && len(ipRecords) > 0 {
							// 将 IP 记录添加到结果中
							records = append(records, ipRecords...)
							err = nil // 清除错误，因为我们找到了结果
						}
					}
				}
			}

			// 如果仍然失败，返回错误
			if err != nil {
				http.Error(w, fmt.Sprintf("DNS 查询失败: %v", err), http.StatusInternalServerError)
				return
			}
		}

		// 如果是 MX 记录且启用了智能查询模式，还需要查询邮件服务器的 IP 地址
		if req.SmartMode && recordType == "MX" && len(records) > 0 {
			var mxHosts []string

			// 提取所有 MX 记录中的邮件服务器主机名
			for _, record := range records {
				if mxRecord, ok := record.(dns.DNSRecord); ok {
					// MX 记录的值格式为 "<priority> <host>"
					parts := strings.Fields(mxRecord.Value)
					if len(parts) >= 2 {
						mxHosts = append(mxHosts, parts[1])
					}
				}
			}

			// 查询每个邮件服务器的 IP 地址
			for _, mxHost := range mxHosts {
				logger.Debug("智能模式: 查询 MX 服务器 IP", "mx_host", mxHost)

				// 查询 A 记录
				ipRecords, ipErr := s.resolver.LookupRecords(ctx, mxHost, dns.RTypeA)
				if ipErr == nil && len(ipRecords) > 0 {
					logger.Debug("智能模式: 找到 MX 服务器 IP", "mx_host", mxHost, "records", len(ipRecords))
					records = append(records, ipRecords...)
				}

				// 查询 AAAA 记录
				ipv6Records, ipv6Err := s.resolver.LookupRecords(ctx, mxHost, dns.RTypeAAAA)
				if ipv6Err == nil && len(ipv6Records) > 0 {
					logger.Debug("智能模式: 找到 MX 服务器 IPv6", "mx_host", mxHost, "records", len(ipv6Records))
					records = append(records, ipv6Records...)
				}
			}
		}

		w.Header().Set("Content-Type", "application/json")
		w.WriteHeader(http.StatusOK)
		json.NewEncoder(w).Encode(map[string]any{
			"domain":  req.Domain,
			"type":    recordType,
			"records": records,
			"ttl":     s.config.DNS.Cache.TTL.Seconds(),
		})
		return
	}

	// 这部分代码已被上面的 switch 语句替换
}

// addCORSHeaders 添加 CORS 头部
func addCORSHeaders(w http.ResponseWriter) {
	w.Header().Set("Access-Control-Allow-Origin", "*")
	w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
	w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")
}

// handleMailDomain 处理邮件域名查询请求
func (s *Server) handleMailDomain(w http.ResponseWriter, r *http.Request) {
	// 添加 CORS 头部
	addCORSHeaders(w)

	// 处理 OPTIONS 请求
	if r.Method == http.MethodOptions {
		w.WriteHeader(http.StatusOK)
		return
	}

	if r.Method != http.MethodPost {
		http.Error(w, "方法不允许", http.StatusMethodNotAllowed)
		return
	}

	// 解析请求体
	var req MailDomainRequest
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		http.Error(w, fmt.Sprintf("无法解析请求体: %v", err), http.StatusBadRequest)
		return
	}

	// 验证域名
	if req.Domain == "" {
		http.Error(w, "域名不能为空", http.StatusBadRequest)
		return
	}

	// 创建上下文
	ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second)
	defer cancel()

	// 增加查询计数
	atomic.AddInt64(s.queryCount, 1)

	// 准备结果数据
	result := make(map[string]any)
	result["domain"] = req.Domain

	// 使用协程并行查询各种记录
	var wg sync.WaitGroup
	var mu sync.Mutex // 保护结果数据的并发写入

	// 1. 查询 MX 记录
	wg.Add(1)
	go func() {
		defer wg.Done()
		// 使用随机 DNS 服务器查询
		mxRecords, mxErr := s.resolver.LookupRecordsFromRandomUpstream(ctx, req.Domain, dns.RTypeMX)

		// 智能模式：查询 MX 记录的 IP 地址
		var mxIPRecords []any
		if req.SmartMode && mxErr == nil && len(mxRecords) > 0 {
			for _, record := range mxRecords {
				if mxRecord, ok := record.(dns.DNSRecord); ok {
					// 提取邮件服务器域名（去除优先级前缀）
					parts := strings.SplitN(mxRecord.Value, " ", 2)
					if len(parts) == 2 {
						mxHost := parts[1]
						// 查询邮件服务器的 IP 地址
						mxIPCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
						defer cancel()

						// 先查询 CNAME
						cnameRecords, _ := s.resolver.LookupRecordsFromRandomUpstream(mxIPCtx, mxHost, dns.RTypeCNAME)
						if len(cnameRecords) > 0 {
							// 如果有 CNAME，添加到结果中
							mxIPRecords = append(mxIPRecords, cnameRecords...)

							// 获取 CNAME 指向的域名
							if cnameRecord, ok := cnameRecords[0].(dns.DNSRecord); ok {
								mxHost = cnameRecord.Value
							}
						}

						// 查询 IP 地址
						ipRecords, _ := s.resolver.LookupRecordsFromRandomUpstream(mxIPCtx, mxHost, dns.RTypeA)
						if len(ipRecords) > 0 {
							mxIPRecords = append(mxIPRecords, ipRecords...)
						}

						// 查询 IPv6 地址
						ipv6Records, _ := s.resolver.LookupRecordsFromRandomUpstream(mxIPCtx, mxHost, dns.RTypeAAAA)
						if len(ipv6Records) > 0 {
							mxIPRecords = append(mxIPRecords, ipv6Records...)
						}
					}
				}
			}
		}

		mu.Lock()
		result["mx"] = map[string]any{
			"records": mxRecords,
			"error":   mxErr,
		}

		// 如果有 MX IP 记录，添加到结果中
		if len(mxIPRecords) > 0 {
			result["mx_ip"] = map[string]any{
				"records": mxIPRecords,
				"error":   nil,
			}
		}
		mu.Unlock()
	}()

	// 2. 查询 SPF 记录 (TXT 记录中的 "v=spf1" 开头的记录)
	wg.Add(1)
	go func() {
		defer wg.Done()
		// 使用随机 DNS 服务器查询
		txtRecords, txtErr := s.resolver.LookupRecordsFromRandomUpstream(ctx, req.Domain, dns.RTypeTXT)
		var spfRecords []any

		// 智能模式：解析 SPF 包含的域名并查询其 IP
		var spfIncludeRecords []any

		if txtErr == nil {
			for _, record := range txtRecords {
				if txtRecord, ok := record.(dns.DNSRecord); ok {
					if strings.HasPrefix(txtRecord.Value, "v=spf1") {
						spfRecords = append(spfRecords, txtRecord)

						// 如果启用了智能模式，分析 SPF 记录中的 include 域名
						if req.SmartMode {
							// 匹配 include:域名 模式
							spfParts := strings.Fields(txtRecord.Value)
							for _, part := range spfParts {
								if strings.HasPrefix(part, "include:") {
									includeDomain := strings.TrimPrefix(part, "include:")

									// 查询包含域名的 SPF 记录
									includeCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
									defer cancel()

									includeTXTRecords, _ := s.resolver.LookupRecordsFromRandomUpstream(includeCtx, includeDomain, dns.RTypeTXT)
									for _, includeTXT := range includeTXTRecords {
										if includeTXTRecord, ok := includeTXT.(dns.DNSRecord); ok {
											if strings.HasPrefix(includeTXTRecord.Value, "v=spf1") {
												spfIncludeRecords = append(spfIncludeRecords, includeTXTRecord)
											}
										}
									}

									// 查询包含域名的 A 记录
									includeARecords, _ := s.resolver.LookupRecordsFromRandomUpstream(includeCtx, includeDomain, dns.RTypeA)
									if len(includeARecords) > 0 {
										spfIncludeRecords = append(spfIncludeRecords, includeARecords...)
									}
								}
							}
						}
					}
				}
			}
		}

		mu.Lock()
		result["spf"] = map[string]any{
			"records": spfRecords,
			"error":   txtErr,
		}

		// 如果有 SPF include 记录，添加到结果中
		if len(spfIncludeRecords) > 0 {
			result["spf_include"] = map[string]any{
				"records": spfIncludeRecords,
				"error":   nil,
			}
		}
		mu.Unlock()
	}()

	// 3. 查询 DMARC 记录 (_dmarc.<domain> 的 TXT 记录)
	wg.Add(1)
	go func() {
		defer wg.Done()
		dmarcDomain := "_dmarc." + req.Domain
		// 使用随机 DNS 服务器查询
		dmarcRecords, dmarcErr := s.resolver.LookupRecordsFromRandomUpstream(ctx, dmarcDomain, dns.RTypeTXT)
		mu.Lock()
		result["dmarc"] = map[string]any{
			"records": dmarcRecords,
			"error":   dmarcErr,
		}
		mu.Unlock()
	}()

	// 4. 查询 DKIM 记录 (selector._domainkey.<domain> 的 TXT 记录)
	// 使用用户提供的 selectors 或默认的常用 selectors
	selectors := []string{"default", "google", "s1", "s2", "dkim", "mail"}
	if len(req.Selectors) > 0 {
		selectors = req.Selectors
	}

	dkimResults := make(map[string]any)
	var dkimMu sync.Mutex // 保护 dkimResults 的并发写入

	// 为每个 selector 创建一个协程
	var dkimWg sync.WaitGroup
	for _, selector := range selectors {
		dkimWg.Add(1)
		go func(sel string) {
			defer dkimWg.Done()
			dkimDomain := sel + "._domainkey." + req.Domain
			// 使用随机 DNS 服务器查询
			dkimRecords, dkimErr := s.resolver.LookupRecordsFromRandomUpstream(ctx, dkimDomain, dns.RTypeTXT)

			// 只添加有结果的 selector
			if dkimErr == nil && len(dkimRecords) > 0 {
				dkimMu.Lock()
				dkimResults[sel] = map[string]any{
					"records": dkimRecords,
					"error":   nil,
				}
				dkimMu.Unlock()
			}
		}(selector)
	}

	// 等待所有主要查询完成
	wg.Wait()

	// 等待所有 DKIM 查询完成
	dkimWg.Wait()
	mu.Lock()
	result["dkim"] = dkimResults
	mu.Unlock()

	// 返回结果
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusOK)
	json.NewEncoder(w).Encode(result)
}

// GetQueryCount 获取查询计数
func (s *Server) GetQueryCount() int64 {
	if s.queryCount == nil {
		return 0
	}
	return atomic.LoadInt64(s.queryCount)
}
